package com.mixsmart.commonweb.service.impl;

import java.util.ArrayList;
import java.util.List;

import com.mixsmart.commonweb.IWebConstant;
import com.mixsmart.commonweb.bean.ISelfClassAssert;
import com.mixsmart.commonweb.dao.TreeDao;
import com.mixsmart.commonweb.service.ITreeService;
import com.mixsmart.spellsql.utils.Cnd;
import com.mixsmart.spellsql.utils.Exp;
import com.mixsmart.utils.CollectionUtils;
import com.mixsmart.utils.StringUtils;

/**
 * 树形服务--实现类
 * @author lmq
 * @version 1.0
 * @since JDK版本大于等于1.6
 * 2016年3月13日
 * @param <T>
 */
public abstract class TreeService<T extends ISelfClassAssert<T>> extends SortNumService<T> implements ITreeService<T> {

	@Override
	public boolean isLeaf(String id) {
		return ((TreeDao<T>)this.getDao()).isLeaf(id);
	}

	@Override
	public Long getChildNum(String id) {
		return ((TreeDao<T>)this.getDao()).getChildNum(id);
	}
	
	/**
	 * 保存树形结构的数据
	 * @param t 树形结构的实体对象 
	 * @return 保存成功返回：true；否则返回：false
	 * @throws MixSmartException
	 */
	protected boolean saveTree(T t) {
		boolean is = false;
		if(null != t) {
			//判断父节点是否为空，如果为空，则表示节点没有具体的父节点，默认设置为属性结构的根节点
			t.setParentId(StringUtils.isEmpty(t.getParentId())?IWebConstant.TREE_ROOT_ID:t.getParentId());
			T parent = getParent(t.getParentId());
			t.setLevel(getLevel(parent));
			if(this.getDao().save(t)) {
				//如果父节点为叶子节点时，更新为非叶子节点
				if(null != parent && parent.getIsLeaf()) {
					parent.setIsLeaf(false);
					this.getDao().update(parent);
				}
			}
			is = true;
		}
		return is;
	}
	
	/**
	 * 更新树形结构的数据
	 * @param t 树形结构的实体对象
	 * @return 更新成功返回：true；否则返回：false
	 * @throws MixSmartException
	 */
	protected boolean updateTree(T t) {
		boolean is = false;
		if(null != t ) {
			//判断父节点是否为空，如果为空，则表示节点没有具体的父节点，默认设置为树形结构的根节点
			t.setParentId(StringUtils.isEmpty(t.getParentId())?IWebConstant.TREE_ROOT_ID:t.getParentId());
			T parent = getParent(t.getParentId());
			t.setLevel(getLevel(parent));
			T oldObj = super.find(t.getId());
			if(null != oldObj) {
				if(!t.getParentId().equals(oldObj.getParentId())) {
					T oldParent = getParent(oldObj.getParentId());
					if(null != oldParent) {
						if(this.getChildNum(oldParent.getId())<2) {
							oldParent.setIsLeaf(true);
						} else {
							oldParent = null;
						}
					}
					oldObj.assertValue(t);
					if(super.update(oldObj)) {
						//如果当前父节点以前为叶子节点，则更新为非叶子节点
						if(null != parent && parent.getIsLeaf()) {
							parent.setIsLeaf(false);
							super.update(parent);
						}
						//如果以前的父节点只有一个叶子节点时,则更新为叶子节点
						if(null != oldParent) {
							super.update(oldParent);
						}
						//如果当前节点是父节点(非叶子节点)时，则更新子节点的level等级
						if(!oldObj.getIsLeaf()) {
							ArrayList<T> childs = new ArrayList<T>();
							getCascadeChilds(childs, new String[]{oldObj.getId()}, oldObj.getLevel());
							if(CollectionUtils.isNotEmpty(childs)) {
								//批量更新子节点对象
								super.update(childs);
							}
						}
						is = true;
					}
				} else {
					oldObj.assertValue(t);
					is = super.update(oldObj);
				}	
			}
		}
		return is;
	}
	
	
	/**
	 * 获取父节点
	 * @param parentId 父节点ID
	 * @return 返回父节点对象
	 */
	protected T getParent(String parentId) {
		T parent = null;
		//非0根节点
		if(!IWebConstant.TREE_ROOT_ID.equals(parentId)) {
			parent = super.find(parentId);
		}
		return parent;
	}
	
	/**
	 * 获取等级
	 * @param parent 父节点
	 * @return 返回等级
	 */
	protected int getLevel(T parent) {
		int level = -1;
		if(null != parent) {
			level = parent.getLevel();
		}
		return level+1;
	}
	
	/**
	 * 级联获取子节点；并给子节点重新设置level等级
	 * @param childs 存放子节点的列表
	 * @param ids 子节点数组
	 * @param level 层级
	 */
	private void getCascadeChilds(List<T> childs, String[] ids, int level) {
		if(CollectionUtils.isEmpty(childs)) {
			childs = new ArrayList<T>();
		}
		List<T> tmps = super.finds(Cnd.where(Exp.in("parentId", ids)));
		if(CollectionUtils.isNotEmpty(tmps)) {
			level++;
			int size = tmps.size();
			ids = new String[size];
			for (int i=0 ; i<size; i++) {
				ids[i] = tmps.get(i).getId();
				tmps.get(i).setLevel(level);
			}
			childs.addAll(tmps);
			getCascadeChilds(childs, ids, level);
		}
	}
}
